#include "stdafx.h"
#include "SimpleCriticalSectionTestSuite.h"

namespace CO { namespace SpiFoundation { namespace RoomFW {

SimpleCriticalSectionTestSuite::SimpleCriticalSectionTestSuite(void)
{
	TEST_ADD(SimpleCriticalSectionTestSuite::wait)
}

void SimpleCriticalSectionTestSuite::wait(void)
{
	CO::SpiFoundation::RoomFW::SimpleEvent first;
	CO::SpiFoundation::RoomFW::SimpleEvent second;
	TEST_ASSERT(first.create(false, false));
	TEST_ASSERT(second.create(false, false));
	EventPair pair(first, second);
	ThreadArg arg(this, &pair);
	x_ = 0;
	TEST_ASSERT(1L != ::_beginthread(ThreadProc, 0, &arg));
	{
		CO::SpiFoundation::RoomFW::CriticalSectionGuard guard(cs_);
		TEST_ASSERT(pair.first.set());
		TEST_ASSERT(pair.second.wait(MaxWait));
		::Sleep(0); // Give up time slice.
		x_ = INT_MAX;
	}
	TEST_ASSERT(pair.first.wait(MaxWait)); // Wait to allow assertions in thread.
}

void SimpleCriticalSectionTestSuite::ThreadProc(void* arg)
{
	ThreadArg* ta = static_cast<ThreadArg*>(arg);
	ta->first->waitProc(ta->second); // Can only TEST_ASSERT in non-static method.
}

void SimpleCriticalSectionTestSuite::waitProc(EventPair* pair)
{
	TEST_ASSERT(pair->first.wait(MaxWait));
	TEST_ASSERT(pair->second.set());
	{
		CO::SpiFoundation::RoomFW::CriticalSectionGuard guard(cs_);
		TEST_ASSERT(INT_MAX == x_);
		TEST_ASSERT(pair->first.set());
	}
}

}}}
